<?php

class Crud_Form extends Zend_Form
{
	/**
	 * Table for building form.
	 * 
	 * @var Crud_Db_Table_Abstract
	 */
	protected $_table;
	
    /**
     * Store Crud_Db_Table in form.
     * -----
     * Registers form view helper as decorator
     *
     * @param Crud_Db_Table_Abstract $table
     * @return void
     */
    public function __construct($table)
    {
    	if (!$table instanceof Crud_Db_Table_Abstract) {
    		throw new Crud_Exception('Unknown table instance given');
    	}
    	
    	$this->_table = $table;
    	parent::__construct();
    	
    	$this->addPrefixPath('Crud_Form_Element', 'Crud/Form/Element/', 'element');
    	$this->addPrefixPath('Crud_Form_Decorator', 'Crud/Form/Decorator', 'decorator');
    	$this->addElementPrefixPath('Validate', 'Validate/', 'validate');
        $this->addElementPrefixPath('Filter', 'Filter/', 'filter');
        $this->addElementPrefixPath('Crud_Form_Decorator', 'Crud/Form/Decorator', 'decorator');
    }
	
	
	/**
	 * Adding element to form.
	 * 
	 * @return void
	 */
	public function init()
	{	
		// Adding Error decorator
		$errorDecorator = new Zend_Form_Decorator_Errors(array(
			'placement' => Zend_Form_Decorator_Abstract::PREPEND
		));
						
		$this->addDecorators(array('FormElements', 'HtmlTag', 'Form', $errorDecorator));
				
		$table = $this->getTable();
		
		// Create elements for each table columns
		$columns = $table->getColumns();
		foreach ($columns as $column) {
			$element = Crud_Form_Element::factory($column);
			$this->addElement($element);
		}
		
		// Create many2many elements for each dependent m2m tables
		$m2mTables = $table->getMany2ManyTables();
		foreach ($m2mTables as $m2mTable) {
			$element = Crud_Form_Element::factory($table, $m2mTable);
			$this->addElement($element);
		}
	
		$this->setMethod(Zend_Form::METHOD_POST);
		
		$submit = new Zend_Form_Element_Submit('submit');
		$submit->setOrder(100);
		$submit->setLabel('Сохранить');
		$this->addElement($submit);
	}
	
	/**
	 * Set default values for form elements by table row.
	 * 
	 * @param Zend_Db_Table_Row_Abstract $row
	 * @return void
	 */
	public function setDefaultsByRow(Crud_Db_Table_Row $row)
	{
		// Set row for adapter cat process file upload
		$elements = $this->getElements();
		foreach ($elements as $element) {
			if ($element instanceof Zend_Form_Element_File) {
				$element->getTransferAdapter()->setDefaultRow($row);
				$element->setAttrib('fileId', $row->getColumnValue($element->getName()));
			}
		}
		
		if ($row->isNew()) return ;
		
		// Set default value for simple columns
		$data = $row->toArray();
		$this->setDefaults($data);
		
		// Set default values for m2m elements
		$table = $this->getTable();
		$m2mTables = $table->getMany2ManyTables();
		foreach ($m2mTables as $m2m) {
			$column = $m2m->getFKColumnFor($table);
			$column3rd = $m2m->getFKColumnNotFor($table);
			
			$select = $m2m->select();
			$name = $column->getName();
			$select->where("`$name` = ?", $row->getColumnValue('id'));
			$rowset = $m2m->fetchAll($select);
			
			$values = array();
			foreach ($rowset as $m2mRow) {
				$values[] = $m2mRow->__get($column3rd->getName());
			}
			
			$name = $m2m->info(Zend_Db_Table_Abstract::NAME);
			$this->setDefault($name, $values);
		}
		
		
	}
	
	/**
	 * Setup crud config.
	 * 
	 * @param Zend_Config $config
	 * @return void
	 */
	public function setCrudConfig($config)
	{
		$elements = $this->getElements();
		foreach ($elements as $element) {
			$name = $element->getName();
			if ($name == 'submit') {
				continue;
			}
			
			$elementConfig = $config->$name;
			if (!$elementConfig || !$elementConfig->item) {
				$this->removeElement($name);
				continue;
			}
			
			if ($elementConfig->label) {
				$element->setLabel($elementConfig->label);
			}
			
			if ($elementConfig->description) {
				$element->setDescription($elementConfig->description);
			}
			
			if ($elementConfig->validators) {
				foreach ($elementConfig->validators as $validator) {
					$element->addValidator($validator);
				}
			}
			
			if ($elementConfig->filters) {
				foreach ($elementConfig->filters as $validator) {
					$element->addFilter($validator);
				}
			}
			
			
		}
	}
	
	/**
	 * Return Crud_Db_Table_Abstract.
	 * 
	 * @return Crud_Db_Table_Abstract
	 */
	public function getTable()
	{
		return $this->_table;
	}
	
    /**
     * Extended method cat add Crud_Form_Element.
     * ------
     * Add a new element
     *
     * $element may be either a string element type, or an object of type
     * Zend_Form_Element. If a string element type is provided, $name must be
     * provided, and $options may be optionally provided for configuring the
     * element.
     *
     * If a Zend_Form_Element is provided, $name may be optionally provided,
     * and any provided $options will be ignored.
     *
     * @param  string|Zend_Form_Element $element
     * @param  string $name
     * @param  array|Zend_Config $options
     * @return Zend_Form
     */
    public function addElement($element, $name = null, $options = null)
    {
    	if ($element instanceof Crud_Form_Element) {
    		$element = $element->getElement();
    		if (!$element) {
    			throw new Crud_Exception('Element is not valid Zend_Form_Element');
    		}
    	}
    	
    	parent::addElement($element, $name, $options);
    }

}
